package system

import (
	"context"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
	"server/internal/dao"
	"server/internal/model"
	"server/internal/model/do"
	"server/internal/service"
)

type sSystemRole struct{}

func init() {
	service.RegisterSystemRole(&sSystemRole{})
}

func (s *sSystemRole) Create(ctx context.Context, in model.SystemRoleCreateInput) (id int64, err error) {
	if err = s.checkCodeIsRepeat(ctx, in.Code, 0); err != nil {
		return 0, err
	}
	in.CreatedBy = service.SystemLogin().GetAdminID(ctx)
	res, _ := dao.SystemRole.Ctx(ctx).Insert(in)
	return res.LastInsertId()
}

func (s *sSystemRole) checkCodeIsRepeat(ctx context.Context, code string, id int64) error {
	where := g.Map{
		"code": code,
	}
	if id > 0 {
		where["id <> ?"] = id
	}
	count, err := dao.SystemRole.Ctx(ctx).Where(where).Count()
	if err != nil {
		return err
	}
	if count > 0 {
		return gerror.New("code 重复")
	}
	return nil
}

func (s *sSystemRole) UpdateById(ctx context.Context, id int64, in model.SystemRoleUpdateInput) error {
	in.UpdatedBy = service.SystemLogin().GetAdminID(ctx)
	_, err := dao.SystemRole.Ctx(ctx).Where(do.SystemRole{Id: id}).Data(in).UpdateAndGetAffected()

	if err == nil {
		service.SystemAuthorityCache().SetSystemPermissionLastUpdatedTime(ctx)
	}

	return err
}

func (s *sSystemRole) DeleteById(ctx context.Context, id int64) error {
	_, err := dao.SystemRole.Ctx(ctx).Data(do.SystemRole{
		DeletedBy: service.SystemLogin().GetAdminID(ctx),
		DeletedAt: gtime.Now(),
	}).Where(do.SystemRole{Id: id}).Update()
	if err == nil {
		service.SystemAuthorityCache().SetSystemPermissionLastUpdatedTime(ctx)
	}
	return err
}

func (s *sSystemRole) List(ctx context.Context, in model.SystemRoleListInput) (roles []model.SystemRoleList, total int, err error) {
	where := g.Map{}
	if len(in.Name) > 0 {
		where["name like ?"] = "%" + in.Name + "%"
	}
	if len(in.Code) > 0 {
		where["code like ?"] = "%" + in.Code + "%"
	}
	err = dao.SystemRole.Ctx(ctx).Where(where).Page(in.Page, in.PageSize).ScanAndCount(&roles, &total, true)

	if len(roles) == 0 {
		return
	}
	roleIds := gdb.ListItemValuesUnique(roles, "Id")

	//角色关联的权限
	_ = dao.SystemPermission.Ctx(ctx).As("p").
		InnerJoin("system_role_permission rp", "rp.permission_id = p.id").
		Fields("p.*,rp.role_id").
		WhereIn("rp.role_id", roleIds).
		ScanList(&roles, "Permissions", "role_id:id")

	//角色关联的用户
	_ = dao.SystemUser.Ctx(ctx).As("u").
		InnerJoin("system_role_user ru", "ru.user_id = u.id").
		Fields("u.*,ru.role_id").
		WhereIn("ru.role_id", roleIds).
		ScanList(&roles, "Users", "role_id:id")

	return
}
